﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Xml;
using SHomeWorkshop.LunarConcept.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月20日前
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：封装两个以上部件。
    /// </summary>
    public class GroupWidget : ContentWidget
    {
        #region 构造方法=====================================================================================================
        
        /// <summary>
        /// [构造方法]
        /// </summary>
        /// <param name="masterEditor"></param>
        public GroupWidget(PageEditorReader masterEditor)
            : base(masterEditor)
        {
            widgetType = Enums.WidgetTypes.Group;
            widgetClassLocalName = Widget.GetWidgetClassLocalName(this.GetType().Name);

            this.widgetPadding = new Thickness(0);                  //默认值为0。
            this.mainBorder.Padding = defaultPadding;//默认值为0。这是为了在组合时方便计算坐标。

            this.widgetLineColor = Brushes.Transparent;
            this.mainBorder.BorderThickness = defaultPadding;

            this.baseStackPanel.Children.Add(this.mainCanvas);
            this.mainBorder.Child = this.baseStackPanel;

            //最后添加文本面板。
            this.baseStackPanel.Margin =
                this.mainTextPanel.Margin = defaultPadding;
            this.baseStackPanel.Children.Add(this.mainTextPanel);
        }

        #endregion


        #region 字段与属性===================================================================================================


        /// <summary>
        /// 主Canvas在此面板内部的上侧，文本区域则在此面板内部的下侧。
        /// </summary>
        private StackPanel baseStackPanel = new StackPanel();
        
        /// <summary>
        /// 默认内部间隙。防止外边框与内容靠得过近——那不好看。
        /// </summary>
        private static Thickness defaultPadding = new Thickness(0);

        private Canvas mainCanvas = new Canvas();
        /// <summary>
        /// [只读]主Canvas。用以承载所有被封装的部件。
        /// </summary>
        public Canvas MainCanvas
        {
            get { return mainCanvas; }
        }

        public bool IsTextAraeVisible
        {
            get
            {
                XmlNode paragraphSetNode = this.ParagraphSetNode;

                if ((paragraphSetNode == null || paragraphSetNode.ChildNodes.Count <= 0) &&
                    string.IsNullOrEmpty(this.AutoNumberString))
                {
                    return false;
                }

                return true;
            }
        }

        #endregion


        #region 方法=========================================================================================================


        /// <summary>
        /// 根据XmlData记录的信息生成部件的内容、设定部件的格式。
        /// </summary>
        public override void Build()
        {
            base.Build();

            //先清除。
            this.mainCanvas.Children.Clear();

            if (this.xmlData == null) return;

            XmlNode widgetSetNode = this.xmlData.SelectSingleNode(XmlTags.WidgetSetTag);
            if (widgetSetNode == null) return;

            XmlNodeList widgetNodeList = widgetSetNode.SelectNodes(XmlTags.WidgetTag);
            foreach (XmlNode node in widgetNodeList)
            {
                Widget w = Widgets.Widget.BuildWidget(this.masterEditor, node);
                if (w != null)
                {
                    mainCanvas.Children.Add(w);

                    if (w is Widgets.LineWidget) continue;
                    else
                    {
                        Widgets.ContentWidget cw = w as Widgets.ContentWidget;
                        if (cw != null)
                        {
                            Canvas.SetLeft(cw, cw.Location.X);
                            Canvas.SetTop(cw, cw.Location.Y);
                        }
                    }
                }
            }

            this.RefreshAutoNumberStrings();//放在RefreshLocation()前面试试，看看会不会影响组的尺寸。
            this.RefreshLocation();

            this.RefreshWidgetBackColor();//刷新由此类调用。读取值都在上级。
            this.RefreshWidgetForeColor();
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
        }
        
        /// <summary>
        /// 重新生成部件本身及其内部封装的所有部件的Id。——这实际上是一个递归方法。
        /// </summary>
        public override void NewID()
        {
            base.NewID();

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widgets.Widget;
                if (w == null) continue;

                w.NewID();//事实上会递归
            }
        }

        /// <summary>
        /// 刷新所有文本块标题的自动编号。ArrowsLineWidget不支持。
        /// 其它部件即使被设置为标题，也只是字形、字号的变化，而不包括自动编号。
        /// </summary>
        public void RefreshAutoNumberStrings()
        {
            int n1Level = 1; int n2Level = 1; int n3Level = 1; int n4Level = 1; int n5Level = 1;
            //只有T1-T5才支持自动编号。截至2012年6月27日，只有T1-T4才支持正式的自动编号。T5暂时全为“◆ ”开头。

            List<Widget> allWidgets = new List<Widget>();

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.Widget w = ue as Widget;

                if (w is ArrowLineWidget) continue;
                else
                    allWidgets.Add(w);
            }

            allWidgets.Sort(new Tools.WidgetCenterYCompareClass());//按纵坐标排序。

            //刷新自动编号。
            foreach (Widgets.Widget w in allWidgets)
            {
                switch (w.TitleLevel)
                {
                    case Enums.TitleStyle.MainTitle:
                        {
                            if (w.AutoNumberString != string.Empty)
                                w.AutoNumberString = string.Empty;

                            n1Level = 1; n2Level = 1; n3Level = 1; n4Level = 1; n5Level = 1;//“切断”自动编号。
                            break;
                        }
                    case Enums.TitleStyle.T1:
                        {
                            w.AutoNumberString = TitleManager.BuildAutoNumberString(Enums.TitleStyle.T1, n1Level);

                            n1Level++;

                            n2Level = 1; n3Level = 1; n4Level = 1; n5Level = 1;//“切断”自动编号。
                            break;
                        }
                    case Enums.TitleStyle.T2:
                        {
                            w.AutoNumberString = TitleManager.BuildAutoNumberString(Enums.TitleStyle.T2, n2Level);

                            n2Level++;

                            n3Level = 1; n4Level = 1; n5Level = 1;//“切断”自动编号。
                            break;
                        }
                    case Enums.TitleStyle.T3:
                        {
                            w.AutoNumberString = TitleManager.BuildAutoNumberString(Enums.TitleStyle.T3, n3Level);

                            n3Level++;

                            n4Level = 1; n5Level = 1;//“切断”自动编号。
                            break;
                        }
                    case Enums.TitleStyle.T4:
                        {
                            w.AutoNumberString = TitleManager.BuildAutoNumberString(Enums.TitleStyle.T4, n4Level);

                            n4Level++;

                            n5Level = 1;//“切断”自动编号。
                            break;
                        }
                    case Enums.TitleStyle.T5:
                        {
                            w.AutoNumberString = TitleManager.BuildAutoNumberString(Enums.TitleStyle.T5, n5Level);

                            n5Level++;

                            break;
                        }
                    default:
                        {
                            w.AutoNumberString = string.Empty; break;
                        }
                }
            }
        }

        public override void RefreshLocation()
        {
            base.RefreshLocation();

            RefreshSize();

            foreach (UIElement ue in this.mainCanvas.Children)
            {
                Widgets.GroupWidget childGroup = ue as GroupWidget;
                if (childGroup == null) continue;
                childGroup.RefreshLocation();//递归调用。
            }
        }

        /// <summary>
        /// 添加到主编辑器的Canvas中后，必须手工调用此方法。
        /// 尺寸由内部所有Widget布局所需要的尺寸决定。
        /// </summary>
        public void RefreshSize()
        {
            if (mainCanvas.Children.Count <= 0)
            {
                this.mainCanvas.Width = this.mainCanvas.Height = 20;
                return;
            }

            double maxRight = 0, maxBottom = 0;//最小左、顶值必是0。

            foreach (UIElement ue in mainCanvas.Children)
            {
                Widget w = ue as Widget;
                if (w == null) continue;

                w.InvalidateArrange(); w.UpdateLayout();

                Point size = w.BottomRight;

                Point wRightBottom = new Point(size.X, size.Y);

                //组合时不再考虑内部线型部件的线宽（情况太复杂）
                //LineWidget lw = w as LineWidget;
                //if (lw != null)
                //{
                //    double halfWidth = lw.LineWidth / 2;
                //    wRightBottom = new Point(wRightBottom.X + halfWidth, wRightBottom.Y + halfWidth);
                //}

                if (wRightBottom.X > maxRight)
                {
                    maxRight = wRightBottom.X;
                }

                if (wRightBottom.Y > maxBottom)
                {
                    maxBottom = wRightBottom.Y;
                }
            }

            if (maxRight > 20) this.mainCanvas.Width = maxRight;
            else this.mainCanvas.Width = 20;

            if (maxBottom > 20) this.mainCanvas.Height = maxBottom;
            else this.mainCanvas.Height = 20;

            return;
        }

        public override void RefreshIsTextVisible()
        {
            //图片框和组有自己的逻辑
            //没有文本内容时“IsTextAreaVisible”优先，文本区域总是不显示，
            //不管继承的“isTextVisible”的值如何。

            if (this.IsTextAraeVisible)
            {
                if (IsTextVisible == false)//注意：不是“IsTextAreaVisible”
                {
                    this.mainTextPanel.Visibility = Visibility.Hidden;
                    this.textHideAdorner.Visibility = Visibility.Visible;
                }
                else
                {
                    this.mainTextPanel.Visibility = Visibility.Visible;
                    this.textHideAdorner.Visibility = Visibility.Collapsed;
                }
            }
            else
            {
                this.mainTextPanel.Visibility = Visibility.Collapsed;
                this.textHideAdorner.Visibility = Visibility.Collapsed;
            }
        }

        public override void RefreshText()
        {
            base.RefreshText();

            RefreshIsTextVisible();

            XmlNode paragraphSetNode = this.ParagraphSetNode;

            if (paragraphSetNode == null || paragraphSetNode.ChildNodes.Count <= 0)
            {
                this.mainTextPanel.Visibility = Visibility.Collapsed;
                return;
            }

            XmlNodeList paragraphNodeList = paragraphSetNode.SelectNodes(XmlTags.ParagraphTag);
            if (paragraphNodeList.Count <= 0)
            {
                this.mainTextPanel.Visibility = Visibility.Collapsed; return;
            }

            if (paragraphNodeList.Count == 1)
            {
                XmlNodeList textNodeList = paragraphNodeList[0].SelectNodes(XmlTags.TextTag);

                if (textNodeList.Count <= 0)
                {
                    this.mainTextPanel.Visibility = Visibility.Collapsed; return;
                }

                if (textNodeList.Count == 1)
                {
                    string text = textNodeList[0].InnerText;
                    if (text == null || text.Length <= 0 ||
                        text == "\r\n" || text == "\r" || text == "\n")
                    {
                        this.mainTextPanel.Visibility = Visibility.Collapsed; return;
                    }
                }
            }

        }

        public override void RefreshTextPanelLocatin()
        {
            //不需要内容。此类的文本面板自动定位。
        }

        #endregion

    }
}
